import { Link, RepoLink } from '@brillout/docpress'
import PreRenderDynamicRoutes from '../pre-rendering/PreRenderDynamicRoutes.mdx'
import { ConfigSpec } from '../../components'

<ConfigSpec
  env="build-time"
/>

The `onBeforePrerenderStart()` hook is executed upon <Link text="pre-rendering" href="/pre-rendering" /> your app.

> It's *only* executed while pre-rendering and, consequently, never executed during development.

It's usually used for:
 - Providing the list of URLs of parameterized routes.
   > If you have a <Link href="/pre-rendering">pre-rendered page</Link> that has a parameterized route such as `/movie/@id`, then you need to provide a list of URLs such as `/movie/1`, `/movie/2`, `/movie/3`, ...
   <PreRenderDynamicRoutes />
 - Fetching data in bulk, in order to make pre-rendering execute faster.


## For providing URLs

Most of the time, the `onBeforePrerenderStart()` hook is used for providing the URLs of parameterized routes.

```ts
// /pages/movie/+route.ts

export default '/movie/@movieId'
```

```ts
// /pages/movie/+onBeforePrerenderStart.ts
// Environment: build-time

export { onBeforePrerenderStart }

async function onBeforePrerenderStart(): Promise<string[]> {
  const movies = await Movie.findAll()
  const moviePageURLs: string[] = movies.map(movie => '/movie/' + movie.id)
  return moviePageURLs
}
```

> If you don't have any parameterized route,
> then you can pre-render your app without defining any `onBeforePrerenderStart()` hook.

> The `onBeforePrerenderStart()` hooks are called when you run <code>$ vike build</code> and, consequently, are never called in development.


## For bulk data fetching

If you have a high number of pages that are to be pre-rendered, then running the command <code>$ vike build</code> may become slow.

You can make pre-rendering significantly faster by providing the <Link href="/pageContext">`pageContext`</Link> of pages in `onBeforePrerenderStart()` hooks.

```ts
// /pages/movie/+route.ts

export default '/movie/@movieId'
```

```ts
// /pages/movie/+onBeforePrerenderStart.ts
// Environment: build-time

export { onBeforePrerenderStart }

type PageContext = {
  data?: Record<string, unknown>
}
type Return = { url: string, pageContext?: PageContext }

async function onBeforePrerenderStart(): Promise<Return[]> {
  const movies = await Movie.findAll()

  const moviePages: Return[] = (
    movies
    .map(movie => {
      const url = '/movie/' + movie.id
      const pageContext = {
        data: {
          movie
        }
      }
      return {
        url,
        // Because we already provide the `pageContext`, Vike will *not* call
        // the `data()` (nor the `onBeforeRender()`) hook for `url`.
        pageContext
      }
      /* We could also only return `url` and not provide `pageContext`. In that case
       * Vike would call the `data()` (and `onBeforeRender()`) hook. But that would be wasteful
       * since we already have all the data of all movies from our `await Movie.findAll()` call.
       * Instead, we provide `pageContext` to make the pre-rendering build step faster.
       */
      // return { url }
    })
  )

  // We can also return URLs that don't match the page's route.
  // That way we can provide the `pageContext` of other pages.
  // Here we provide the `pageContext` of the `/movies` page since
  // we already have the data.
  const movieListPage: Return = {
    url: '/movies', // Note how this URL '/movies' doesn't match the page's route /movie/@movieId
    pageContext: {
      data: {
        // We filter out the data we don't need in order to minimize what is sent
        // to the browser. We explain this practice at https://vike.dev/data-fetching
        movieList: movies.map(({id, title}) => ({id, title}))
      }
    }
  }

  return [movieListPage, ...moviePages]
}
```

Essentially, the `onBeforePrerenderStart()` hook allows you to prefetch data for multiple pages at once.

> <p><b>Providing <code>pageContext</code> in <code>onBeforePrerenderStart()</code> hooks should only be used for making pre-rendering faster</b> and
> we recommend against using <code>onBeforePrerenderStart()</code> hooks for other purposes.</p>
>
> For example, avoid providing additional `pageContext` values in `onBeforePrerenderStart()` hooks that wouldn't otherwise exist. Because `onBeforePrerenderStart()` hooks are never called in development and it's best to keep your app consistent between development and production.


## Examples

React Example:
 - <RepoLink path='/examples/react-full/pages/star-wars/index/+onBeforePrerenderStart.ts' />
 - <RepoLink path='/examples/react-full/pages/hello/+onBeforePrerenderStart.ts' />

Vue Example:
 - <RepoLink path='/examples/vue-full/pages/star-wars/index/+onBeforePrerenderStart.ts' />
 - <RepoLink path='/examples/vue-full/pages/hello/+onBeforePrerenderStart.ts' />


## See also

- <Link href="/pre-rendering" />
- <Link href="/onPrerenderStart" />
- <Link href="/hooks" />
